package com.chris.design.pattern.demo;

import javax.tools.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URI;
import java.util.Arrays;

/**
 *  基于字符串的动态编程实现
 *
 * @author Chris
 * @since 2019/9/26
 */
public class CompileString {

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        JavaCompiler systemJavaCompiler = ToolProvider.getSystemJavaCompiler();
        System.out.println("===systemJavaCompiler==>>" + systemJavaCompiler);
        StandardJavaFileManager standardFileManager = systemJavaCompiler.getStandardFileManager(null, null, null);

        // x * y
        StringObject so = new StringObject(
                "CalculatorTest",
                "class CalculatorTest {"
                        + " public int multiply(int multiplicand, int multiplier) {"
                        + " System.out.println(multiplicand);"
                        + " System.out.println(multiplier);"
                        + " return multiplicand * multiplier;" + " }" + "}");

        JavaFileObject file = so;

        Iterable files = Arrays.asList(file);
        JavaCompiler.CompilationTask task = systemJavaCompiler.getTask(null, standardFileManager, null, null, null, files);
        Boolean call = task.call();
        System.out.println("=====call==>>" + call);
        if (call) {
            Class<?> clazz = Class.forName("CalculatorTest");
            Object instance = clazz.newInstance();
            Method m = clazz.getMethod("multiply", new Class[]{int.class, int.class});
            Object[] o = new Object[] {3, 2};
            System.out.println(m.invoke(instance, o));
        }
    }

}

class StringObject extends SimpleJavaFileObject {
    private String contents = null;

    public StringObject(String clazzName, String contents) {
        super(URI.create("string:///" + clazzName.replace(".", "/") + Kind.SOURCE.extension), Kind.SOURCE);
        this.contents = contents;
    }

    @Override
    public CharSequence getCharContent(boolean ignoreEncodingErrors) {
        return contents;
    }
}
